package com.wangbo.delayQueue;

import com.wangbo.delayQueue.DelayTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.Base64;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.DelayQueue;

import static java.nio.charset.StandardCharsets.UTF_8;

@Slf4j
@Component
public class ScheduledTasks {
    public final DelayQueue<DelayTask> delayQueue = new DelayQueue<>();
    public final ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue();

    // 准备数据
//    {
//        for(int i = 0; i< 10;i++) {
//            long now = System.currentTimeMillis();
//            Map<String, Object> result = new HashMap<>();
//            UserAddParam param = new UserAddParam(i, RandomUtil.randomString(6));
//            result.put("param", param);
//            delayQueue.add(new DelayTask(now + 3000L * i, Contants.DELAY_TASK_BIZ_TYPE_USER_ADD, result));
//        }
//
//        for (int i = 0; i < 100; i++) {
//            queue.add(i);
//        }
//    }

    /**
     * 定期处理延迟队列
     */
//    @Scheduled(fixedDelay = 100L)
//    public void scheduleProcessDelayQueue() throws InterruptedException {
//        DelayTask delayTask = delayQueue.poll();
//        while (delayTask != null) {
//            switch (delayTask.bizType) {
//                case 1:
//                    ObjectMapper objectMapper = new ObjectMapper();
//                    Map result = objectMapper.convertValue(delayTask.param, Map.class);
//                    UserAddParam param = objectMapper.convertValue(result.get("param"), UserAddParam.class);
//                    log.info("延迟任务，param={}", param);
//                    Thread.sleep(3000L);
//                    break;
//            }
//            delayTask = delayQueue.poll();
//        }
//    }

    /**
     * @Scheduled 测试
     * 结论：@Scheduled 默认使用 Single 线程池处理所有定时任务，任务之间会互相影响，需要搭配 TaskScheduler
     */
//    @Scheduled(fixedDelay = 100L)
//    public void scheduleTask() throws InterruptedException {
//        Integer task = queue.poll();
//        while (task != null) {
//            log.info("任务ID={}", task);
//            Thread.sleep(1000L);
//            task = queue.poll();
//        }
//    }

//    @Scheduled(fixedDelay = 1000L)
//    public void scheduleExceptionTask() {
//        log.info("要出异常了，请准备好");
//        int a = 1 / 0;
//    }

    /**
     * 测试定期调用 restTemplate 如果连接超时，是否会使定时任务中断
     * 结论：restTemplate 连接超时不会造成定时任务中断
     */
//    @Scheduled(fixedDelay = 1000L)
//    public void scheduleExceptionTask() {
//        log.info("要出异常了，请准备好");
//        RestTemplate restTemplate = new RestTemplateBuilder()
//                .setConnectTimeout(Duration.ofSeconds(3L))
//                .setReadTimeout(Duration.ofSeconds(3L))
//                .errorHandler(new DefaultResponseErrorHandler(){
//                    /**
//                     * 设置RestTemplate自带的异常处理器不做异常处理
//                     **/
//                    @Override
//                    public void handleError(ClientHttpResponse response) {
//                    }
//                }).build();
//
//        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
//        param.add("username","wangbo");
//        param.add("password", Base64.getEncoder().encode("123456".getBytes(UTF_8)));
//
//        String url = String.format("http://%s:%d/service/api/%s", "139.196.32.5", 8080, "user/login");
//        String token = restTemplate.postForObject(url, param, String.class);
//        System.out.println("token");
//    }
}
